package com.da.landlord;

import java.io.IOException;
import java.io.PrintWriter;
import java.math.BigDecimal;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;

import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.struts2.ServletActionContext;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.da.finance.DaFinanceStatementService;
import com.googlecode.cswish.annotation.Rest;
import com.googlecode.cswish.exception.ApplicationException;
import com.googlecode.cswish.model.PageInfo;
import com.googlecode.cswish.model.Reference;
import com.googlecode.cswish.oosearch.Condition;
import com.googlecode.cswish.oosearch.QLInfo;
import com.googlecode.cswish.struts.ServletRedirectResult;
import com.googlecode.cswish.struts.spring.GenericService;
import com.googlecode.cswish.struts.spring.ObjectFactory;
import com.googlecode.cswish.struts.spring.SearchCallback;
import com.googlecode.cswish.util.bean.ModelUtil;
import com.opensymphony.xwork2.Result;
import com.ra.external.BuildingInfoService;
import com.ra.external.RoomInfoService;
import com.ra.external.RoomRetrievalService;
import com.ra.landlord.FeeRuleCfg;
import com.ra.landlord.FeeRuleCfgService;
import com.ra.landlord.LandlordAssistUser;
import com.ra.landlord.LandlordUser;
import com.ra.landlord.LandlordUserService;
import com.ra.landlord.Room;
import com.ra.landlord.TenantUser;
import com.ra.landlord.constant.FeeRuleCalcMode;
import com.ra.landlord.constant.FeeRuleType;
import com.ra.order.rental.RentalOrderService;
import com.ra.util.Address;
import com.ra.util.AddressCode;
import com.ra.util.AddressCodeService;
import com.ra.util.DateTimeUtil;

/**
 * 房源service
 * @author Peter Z
 *
 */
@Service
public class DaSuiteService {

	private static final Log logger = LogFactory.getLog(DaSuiteService.class);

	@Resource
	private GenericService genericService;

	@Resource
	private LandlordUserService landlordUserService;
	
	@Resource
	private DaChargeItemService daChargeItemService;
	
	@Resource
	private RentalOrderService rentalOrderService;
	
	@Resource
	private ObjectFactory objectFactory;
	
	@Resource
	private FeeRuleCfgService feeRuleCfgService;
	
	@Resource
	private DaFinanceStatementService daFinanceStatementService;
	
	@Resource
	private RoomRetrievalService roomRetrievalService;
	
	@Resource
	private RoomInfoService roomInfoService;
	
	@Resource
	private BuildingInfoService buildingInfoService;
	
	@Resource
	private AddressCodeService addressCodeService;
	
	private DaSuiteService daSuiteService;
	
	private DaSuiteService getThis() {
		if (daSuiteService == null) {
			daSuiteService = ObjectFactory.getInstance().getBean(DaSuiteService.class, false);
		}
		return daSuiteService;
	}
	
	/**
	 * 进入房源管理页面 显示所有的房源信息
	 * 可进行房源查询、分页操作等。 以及其它操作(新增，修改，删除)
	 * @return List<DaSuite>
	 */
	@Rest(type = "search")
	public PageInfo<DaSuite> manager(DaSuite model,int start,int limit,String sort, String dir, boolean oldSearch, Reference<QLInfo> qlInfoRef,Integer chargeSate,String tenantUserName, Integer expiredLeave ) {
		logger.info("进入房源管理页面");
		
		final Integer rentState = model.getRentState();
		model.setRentState(null);
		SearchCallback callback = new SearchCallback() {

			@Override
			public QLInfo afterBuildQL(boolean newSearch, QLInfo qlInfo) {
				if (newSearch) {
					if (rentState != null) {
						if (rentState == 0) {
							qlInfo.andClause("(a.rentState = 0 or a.rentState = 2)");
						} else if (rentState == 1) {
							qlInfo.andClause("(a.rentState = 1 or a.rentState = 2)");
						}
					}
				}
				return qlInfo;
			}
		};
		
		//如果当前登录用户时房东管理员，则获取的房源只能是其分配到的
		LandlordUser loginLandlordUser = landlordUserService.getLoginUser();
		if (loginLandlordUser instanceof LandlordAssistUser)
		{
			List<LandlordUser> assists = new ArrayList<LandlordUser>();
			assists.add(loginLandlordUser);
			model.setLandlordUsers(assists);
		}
		
		PageInfo<DaSuite> pageInfo =  genericService.search(model, start, limit, "createDate", "desc", oldSearch, qlInfoRef, callback, true, false);
		
		//出租状态
		model.setRentState(rentState);
		
		//匹配出租状态结果集  
		if(rentState != null){
			//根据索引条件不要的情况
			List<DaSuite> suites = pageInfo.getData();
			List<DaSuite> resultSuite = new ArrayList<DaSuite>();
			for (DaSuite daSuite : suites) {
				List<DaRoom> rooms = daSuite.getRooms();
				List<DaRoom> resultRooms = new ArrayList<DaRoom>();
				for (DaRoom daRoom : rooms) {
					if(rentState.equals(daRoom.getRentState())){
						resultRooms.add(daRoom);
					}
				}
				daSuite.setRooms(resultRooms);
				resultSuite.add(daSuite);
			}
			
			pageInfo.setData(resultSuite);
			
		}
		
		//收费状态查询 0已缴费 1未交  ---0对应false说明不存在收费项 1对应true说明存在收费项
		if (chargeSate !=null){
			Boolean chargeS=(chargeSate==0?false:true);
			//根据索引条件不要的情况
			List<DaSuite> suites = pageInfo.getData();
			List<DaSuite> resultSuite = new ArrayList<DaSuite>();
			for (DaSuite daSuite : suites) {
				List<DaRoom> rooms = daSuite.getRooms();
				List<DaRoom> resultRooms = new ArrayList<DaRoom>();
				for (DaRoom daRoom : rooms) {
					if(chargeS.equals(daRoom.getChargeSate()) && daRoom.getRentState()==0){
						resultRooms.add(daRoom);
					}
				}
				daSuite.setRooms(resultRooms);
				resultSuite.add(daSuite);
			}
			pageInfo.setData(resultSuite);
		}
		
		//根据租客信息来匹配出房间 tenantUser.name  tenantUserName
		if (StringUtils.isNotEmpty(tenantUserName)){
			//根据索引条件不要的情况
			List<DaSuite> suites = pageInfo.getData();
			List<DaSuite> resultSuite = new ArrayList<DaSuite>();
			for (DaSuite daSuite : suites) {
				List<DaRoom> rooms = daSuite.getRooms();
				List<DaRoom> resultRooms = new ArrayList<DaRoom>();
				for (DaRoom daRoom : rooms) {
					if(daRoom.getAgreement()!=null && daRoom.getRentState() == 0){
						TenantUser user = daRoom.getAgreement().getTenantUser();
						if( user != null && user.getName().contains(tenantUserName)){
							resultRooms.add(daRoom);
						}
					}
				}
				daSuite.setRooms(resultRooms);
				resultSuite.add(daSuite);
			}
			pageInfo.setData(resultSuite);
		}
		
		if (expiredLeave != null) {
			Calendar now = Calendar.getInstance();
			if (expiredLeave !=null) {
				now.add(Calendar.DATE, expiredLeave);
			}
			List<DaSuite> suites = pageInfo.getData();
			List<DaSuite> resultSuite = new ArrayList<DaSuite>();
			for (DaSuite daSuite : suites) {
				List<DaRoom> rooms = daSuite.getRooms();
				List<DaRoom> resultRooms = new ArrayList<DaRoom>();
				for (DaRoom daRoom : rooms) {
					if(daRoom.getAgreement()!=null && daRoom.getAgreement().getRentEndDate().compareTo(now.getTime()) <= 0){
						resultRooms.add(daRoom);
					}
				}
				daSuite.setRooms(resultRooms);
				resultSuite.add(daSuite);
			}
			pageInfo.setData(resultSuite);
		}
		
		//费用自动计算
		//daChargeItemService.autoCreateChargeItem();
		return pageInfo;
	}
	
	
	/**
	 * 查询单个Dasuite
	 * @param model
	 * @return
	 */
	@Rest(type = "search")
	public DaSuite view( DaSuite model ){
		model = genericService.view( model);
		return model;
	}
	
	
	/**
	 * 查询单个房间信息
	 * @param model
	 * @return
	 */
	@Rest(type = "search")
	public DaRoom viewRoom( DaRoom model ){
		model = genericService.view( model);
		return model;
	}
	
	

	/**
	 * 删除房间 用于ajax 调用
	 * @param model
	 * @return
	 */
	@Rest(type = "delete")
	public boolean deleteRooms( List<DaSuite> model ){
		
		logger.info("deleteDasuite");
		List<Integer> deletedSuiteIds = getThis().deleteRoomsInTrans(model);
		for (Integer suiteId : deletedSuiteIds) 
		{
			buildingInfoService.deleteSuiteInfo(suiteId);
		}				
		return true;
		
	}
	
	@Transactional
	public List<Integer> deleteRoomsInTrans(List<DaSuite> model)
	{
		boolean result = true;
		List<Integer> deletedSuiteIds = new ArrayList<Integer>(model.size());
		try {
			for (DaSuite daSuite : model) {
				daSuite = genericService.view(daSuite);
				if(DaSuite.RENTSTATE_FREE.equals(daSuite.getRentState())){
					rentalOrderService.deleteRentalOrderBy(daSuite);
					genericService.delete(daSuite);
					
					deletedSuiteIds.add(daSuite.getId());
					
				}else{
					result = false;
				}
			}
		} catch (Exception e) {
			logger.error("删除Da房源失败", e);
			throw new ApplicationException("系统忙，请稍后再试!");
		}
		
		if(result == false){
			throw new ApplicationException("只能空闲的房源才能删除!");
		}
		
		return deletedSuiteIds;
	}
	
	@Rest(type = "rentRoom")
	public DaRoom _rentRoom( DaRoom model){
		if( model.getId() != null){
			model = genericService.view( model );
		}
		return model;
	}
	
	
	/**
	 * 房源出租
	 * @param model
	 * @return
	 */
	@Rest(type = "rentRoom")
	public Result rentRoom(DaAgreement model,Integer fromManager){
		Result result = null;
		
		if( model.getId()!=null ){
			
			result = new ServletRedirectResult("/da/landlord/daSuite.manager.html");
			objectFactory.autoWireBean(result);
			updateRentMessage(model);
			return result;
			
		}else{
			//设置合约为有效合约
			 model.setAgreementState(0); 
			 
			//取出出租对应的房源
			DaRoom room = model.getRoom();
			
			//为关联处理把room load到内存中
			room = genericService.load(room,false);
			
			
			//设置相关跳转
			if(fromManager!=null){
				result = new ServletRedirectResult("/da/landlord/daSuite.manager.html");
			}else{
				if( room.getSuite().getRentType() == 1){
					result = new ServletRedirectResult("/da/landlord/daSuite.viewRoom.html?model.id="+room.getId());
				}else{
					result = new ServletRedirectResult("/da/landlord/daSuite.view.html?model.id="+room.getSuite().getId());
				}
			}
			objectFactory.autoWireBean(result);
			
			
			if(room.getRentState()!=null && room.getRentState().equals(0)){
				//此房已经出租，不可再次出租 
				model.setRemark("此房已经出租，不能再次出租！！");
				return result;
			}
			
			DaSuite suite = room.getSuite();
			
			changeRoomWithAgreement(model, room);
			
			//根据房源的出租类型，确认是整套出租还是单个房源出租
			Integer rentType = suite.getRentType();
			
			if(rentType == 0){
				suite.setRentState(0);
			}else if(rentType == null){
				throw new ApplicationException("错误的房源类型");
			}
			
			
			
			// 新增合约同时，把内存中的room同步到数据库
			model = genericService.add(model);
			room.setAgreement(model);
			
			//出租时默认收取一笔费用。
			daChargeItemService.createFirstChargeItems(room, model);
			
			//一定要在room改变自身状态之后执行下面的同步语句。
			synSuiterentStatus(suite.getId());
			
			//取消发布房源
			roomRetrievalService.unPublishDaRoom(room);
			
			return result;
		}
	}

	
	/**
	 * 修改合约信息  此方法存在安全问题，待验证 //TODO 改变合约后，应对应修改掉合约信息,到期日，要重新计算，此功能待完善。如续租
	 * @param model
	 */
	private void updateRentMessage(DaAgreement model) {
		
		DaAgreement oldObject = new DaAgreement();
		oldObject.setId(model.getId());
		oldObject = genericService.load(oldObject);
		
		if (!model.getPayNum().equals(oldObject.getPayNum())) { //押几付几模式发生变化，需要重新生成费用
			DaChargeItem chargeItemExample = new DaChargeItem();
			chargeItemExample.setName("房租");
			chargeItemExample.setStatus(DaChargeItem.STATUS_CONFIRMED);
			chargeItemExample.setRoom(oldObject.getRoom());
			List chargeItems = genericService.searchByModel(chargeItemExample,Condition.DEFAULT).getData();
			if (chargeItems.size() != 0) {
				genericService.deleteList(chargeItems);
				//进入dasuite。manager会自动产生费用
			}
		}
		
		ModelUtil.deepCopy(model, oldObject, Arrays.asList("rentPay",
				"deposit", "rentPeriod", "rentCycleType", "advanceNum", "payNum", "remark"));
		
		TenantUser oldUser = oldObject.getTenantUser();
		
		TenantUser newUser = model.getTenantUser();
		
		ModelUtil.deepCopy(newUser, oldUser, Arrays.asList("name","gender", "idCard", "phone"));
		
		oldObject.setTenantUser(oldUser);
		
		genericService.merge(oldObject);
		
		DaRoom room = oldObject.getRoom();
		
		// change the end date of deposite charge
		DaChargeItem chargeItemExample = new DaChargeItem();
		chargeItemExample.setName("押金");
		chargeItemExample.setStatus(DaChargeItem.STATUS_PAID);
		chargeItemExample.setRoom(room);
		List<DaChargeItem> chargeItems = genericService.searchByModel(chargeItemExample,Condition.DEFAULT).getData();
		
		if (chargeItems.size() > 0){
			DaChargeItem dbDepositeChargeItem = chargeItems.get(0);
			Integer totalMonth = oldObject.getRentCycleType() == 0 ? oldObject.getRentPeriod() : oldObject.getRentPeriod() * 12;
			Date endDate = daChargeItemService.getEndDate(-1, daChargeItemService.getEndDate(totalMonth,oldObject.getRentBeginDate(),2),5);
			dbDepositeChargeItem.setDateEndRecv(endDate);
			genericService.merge(dbDepositeChargeItem);
		}
		
	}


	/**
	 * 根据出租情况，设置数据库suite的特殊状态
	 * @param suiteid
	 */
	@Rest(type = "update")
	public void synSuiterentStatus(Integer suiteid){
		DaSuite suite = new DaSuite();
		suite.setId(suiteid);
		suite = genericService.load(suite);
		
		int roomCount = suite.getRooms().size();
		int i = 0;
		for (; i< suite.getRooms().size(); i++) {
			DaRoom room = suite.getRooms().get(i);
			if (DaRoom.RENT_STATE_UNRENT != room.getRentState()){
				suite.setRentState(DaSuite.RENT_TYPE_ENTIRE);
				break;
			}
		}
		
		if (i == suite.getRooms().size()) {
			suite.setRentState(DaSuite.RENTSTATE_FREE);
		}
		
	/*	int rentSize = suite.getRentRooms().size();
		
		Integer result = null;
		
		if(rentSize == 0 ){
			//全部未出租
			result = 1;
		}else if(rentSize<roomCount){
			//部份出租
			result = 2;
		}else{
			//表示全部已出租
			result = 0;
		}
		suite.setRentState(result);*/
		
		genericService.merge(suite);
	}
	
	
	
	
	/**
	 * 当合约产生时 设置相关同步信息
	 * @param model
	 * @param room
	 */
	private void changeRoomWithAgreement(DaAgreement model, DaRoom room) {
		//设置房间状态为已出租
		room.setRentState(0);
		
		// 为租客设置一些默认值
		setDefaultTenantUser(model);
		
		// 计算合约结束日期
		Date d = model.getRentBeginDate();
		
		Calendar c = Calendar.getInstance();
		c.setTime( d );
		
		Integer rentCycleType = model.getRentCycleType();
		
		if( rentCycleType !=null && rentCycleType.equals(0) ){
			//出租周期是多少月
			c.add(2,  model.getRentPeriod() );
		}else{
			//出租周期为多少
			c.add(1,  model.getRentPeriod() );
		}
		
		model.setRentEndDate( c.getTime() );
		
	}


	/**
	 * 设置默认的出租用户信息
	 * @param model
	 */
	private void setDefaultTenantUser( DaAgreement model ) {
		//计算生日
		model.getTenantUser().setBirthday( DateTimeUtil.getBirthday( model.getTenantUser().getIdCard()) );
		//为用户设置初使密码
		model.getTenantUser().setPassword( "123456" );
		//为用户设置其它默认信息
		model.getTenantUser().setCertificateType( 0 );
		model.getTenantUser().setRegister( new Date() );
		
		//model.getTenantUser().setStatus( 1 );
		//model.getTenantUser().setVersion( 1 );
	}
	
	
	/**
	 * 进入添加/修改 房源页面 表单
	 */
	@Rest(type = "update")
	public DaSuite _update(DaSuite model,  DaAgreement agreement) {
		if (model.getRooms() == null) {
			model.setRooms( new ArrayList<DaRoom>(2) );
		}
		for (int i = model.getRooms().size(); i < 2; i++) {
			model.getRooms().add(new DaRoom());
		}
		
		if(model == null ||null == model.getId()){
			return model;
		}
		
		model = genericService.view(model);
		
		return model;
	}

	
	
	/**
	 * 用于添加房源 
	 * 
	 * @param model
	 * @return 新加的房源id
	 */
	@Rest(type = "add")
	public void addSuite(DaSuite model) {
		
		DaSuite updatedDaSuite;
		if (model.getId() == null)
		{
			//Add
			updatedDaSuite = getThis().addDaSuite(model);
		}
		else
		{
			//Update
			updatedDaSuite = getThis().updateDaSuite(model);
		}
		buildingInfoService.updateDaSuiteInfoAsync(updatedDaSuite);
		
		//自动发布房源
		publishDaRooms(updatedDaSuite.getRooms());
		//得定向到列表页面
		try 
		{
			PrintWriter out = ServletActionContext.getResponse().getWriter();
			out.println("<script>top.Core.loadpage('/da/landlord/room._search.html');</script>");
			out.flush();
			out.close();
		} 
		catch (IOException e) 
		{
			logger.error("Fail to forward to room._search.html", e);
		}
	}
	
	/**
	 * 发布分布式房源
	 * @param dbRooms
	 */
	private void publishDaRooms(List<DaRoom> dbRooms)
	{
		//自动发布房源
		if (dbRooms != null && !dbRooms.isEmpty())
		{
			for (DaRoom dbRoom : dbRooms)
			{
				roomRetrievalService.publishDaRoom(dbRoom, false);
			}
		}
	}
	
	
	/**
	 * 为房源绑定地址
	 * @param model
	 * @return
	 */
	private DaSuite setAddress(DaSuite model) {
		Address address = model.getAddress();
		AddressCode addressCode  = address.getAddressCode();
		if(addressCode.getId()!=null){
			addressCode = genericService.load(addressCode);
		}
		
		address.setAddressCode(addressCode);
		//封装必须元素
		/*address.setProvince(addressCode.getCodeByLevel(AddressCode.LEVEL_PROVINCE));
		address.setCity(addressCode.getCodeByLevel(AddressCode.LEVEL_CITY));
		address.setDistrict(addressCode.getCodeByLevel(AddressCode.LEVEL_DISTRICT));*/
		
		address.setProvince(addressCodeService.getCodeByLevel(addressCode, AddressCode.LEVEL_PROVINCE));
		address.setCity(addressCodeService.getCodeByLevel(addressCode, AddressCode.LEVEL_CITY));
		address.setDistrict(addressCodeService.getCodeByLevel(addressCode, AddressCode.LEVEL_DISTRICT));
		/*address.setVersion(1);
		address.setStatus(0);*/
		
		address.setName("");  //address.setName 只设定街道地址
		model.setAddress(address);
		
		return model;
	}




	/**
	 * 跳转到测试页面
	 */
	@Rest(type="update")
	public void vali(){
		
	}
	
	/**
	 * 新增分散式房源   注: 内部调用,非页面直接调用
	 * @param model
	 * @return
	 */
	@Transactional
	public DaSuite addDaSuite(DaSuite model)
	{
		//为feeRule设置默认值 
		List<DaFeeRule> rules = model.getFeeRules();
		if (rules != null) {
			for (DaFeeRule daFeeRule : rules) {
				daFeeRule.setState(1);
			}
			model.setFeeRules(rules);
		}
		
		List< DaRoom >  rooms = null;
		
		model = setAddress(model);
		model.setCreateDate(new Date());
		switch (model.getRentType()) 
		{
			case 0 : {
				
				//整租情况，产生一个room,并保存房源 
				rooms = new ArrayList<DaRoom>();
				DaRoom room = new DaRoom();
				room.setRentPay( model.getRentPay() );
				room.setArea( model.getArea() );
				room.setDepositNum( model.getDepositNum() );
				room.setLandlordUser( model.getLandlordUser() );
				room.setName( model.getName() );
				room.setOrientation( model.getOrientation() );
				room.setPayNum( model.getPayNum() );
				room.setRentPay( model.getRentPay() );
				room.setRentState( 1 );
				rooms.add( room );
				
				//为未出租
				model.setRentState( 1 );
				model.setRooms( rooms );
				break;
				
			}
			case 1 : {
				//分租情况，从参数当中取出来room，然后分别进行保存
				rooms = model.getRooms();
				for ( DaRoom daRoom : rooms ) {
					
					if(daRoom.getRoomItem() == null ){
						daRoom.setRoomItem( new DaRoomItem() );
					}
					
					//初使化为未出租状态
					daRoom.setRentState(1);
					daRoom.setAgreement( null);
					daRoom.setOrientation(model.getOrientation());
					
					List<DaFeeRule> roomrules = daRoom.getFeeRules();
					if (roomrules != null) {
						for (DaFeeRule daFeeRule : roomrules) {
							daFeeRule.setState(1);
						}
					}
				}
				model.setRentState( 1 );
				model.setRooms(rooms);
				break;
			}
			default : {
				break;
			}
		}//switch
		
		LandlordUser loginUser = landlordUserService.getLoginUser();
		if (loginUser instanceof LandlordAssistUser) 
		{
			
			List<LandlordUser> assists = new ArrayList<LandlordUser>();
			assists.add(loginUser);
			model.setLandlordUsers(assists);
		} 
		
		DaSuite addedDaSuite = genericService.add( model );
		return addedDaSuite;
	}
	
	/**
	 * 判断是否修改操作，如果是，则进行修改并返回true. 注: 内部调用,非页面直接调用
	 * @param model
	 * @param agreement
	 * @return
	 */
	@Transactional
	public DaSuite updateDaSuite(DaSuite model) {
		
		DaSuite oldModel = genericService.load(model, false);
		
		if (oldModel == null){
			throw new ApplicationException("不存丰修改的对象!");
		}
		setAddress(model);
		ModelUtil.deepCopy(model, oldModel, Arrays.asList("rentType",
				"name", "area", "orientation", "floorCount", "floorNo",
				"rentPay", "depositNum", "payNum", "roomCount",
				"hallCount", "decorateLevel","toiletCount", "toiletCount","mark"));//如果这里不存在reeRules的id，那么是否变为新增
		
		oldModel.setAddress(model.getAddress());
		List<DaFeeRule> formRules = model.getFeeRules();
		oldModel = corrFeeRules(formRules,oldModel);
		
		List<DaSuiteAttachment> formAttach = model.getAttachments();
		oldModel = corrImg(formAttach,oldModel);
		
		//rentRooms //address
		DaSuiteItem suiteItem = model.getSuiteItem();
		if ( null != suiteItem ){
			DaSuiteItem oldItem = oldModel.getSuiteItem(); 
			
			ModelUtil.deepCopy(suiteItem, oldItem, Arrays.asList(
					"airCondition", "armoire", "balcony", "bed",
					"broadband", "desk", "freezer", "gas", "heater",
					"kitchen", "toilet", "tv", "washingMachine", "elevator"));
			
			oldModel.setSuiteItem(oldItem);
		}
		
		if (model.getRentType() == 0){
			//整租情况
			List<DaRoom> oldRooms = oldModel.getRooms();
			if( null != oldRooms && oldRooms.size()>0 ){
				DaRoom oldRoom = oldRooms.get(0);
				if( null != oldRoom ){
					oldRoom.setRentPay( model.getRentPay() );
					oldRoom.setArea( model.getArea() );
					oldRoom.setDepositNum( model.getDepositNum() );
					oldRoom.setLandlordUser( oldModel.getLandlordUser() );
					oldRoom.setName( model.getName() );
					oldRoom.setOrientation( model.getOrientation() );
					oldRoom.setPayNum( model.getPayNum() );
					oldRoom.setRentPay( model.getRentPay() );
					oldRoom.setRentState( oldModel.getRentState() );
				}
				oldRooms = new ArrayList<DaRoom> ();
				oldRooms.add(oldRoom);
				oldModel.setRentRooms(oldRooms);
			}
			oldModel = genericService.merge(oldModel);
			
		}else{
			//合租情况
			List<DaRoom> oldRooms = oldModel.getRooms();
			List<DaRoom> newRooms = model.getRooms();
			List<DaRoom> resultRooms = new ArrayList<DaRoom>();
			
			if( null != oldRooms && oldRooms.size()>0 ){
				int oldRoomsSize = oldRooms.size();
				int i = 0;
				//修改所有已有的房间 只能加不能减
				for(; i<oldRoomsSize; i++){
					DaRoom oldRoom = oldRooms.get(i);
					DaRoom newRoom = newRooms.get(i);
					ModelUtil.deepCopy(newRoom, oldRoom, Arrays.asList("rentPay","roomNum","area", "depositNum","name","orientation","payNum","rentPay","sex","checkInNum","roomType"));
					
					DaRoomItem oldItem = oldRoom.getRoomItem()==null?new DaRoomItem():oldRoom.getRoomItem();
					oldItem.setRoom(oldRoom);
					DaRoomItem newItem = (newRoom.getRoomItem()==null)?new DaRoomItem():newRoom.getRoomItem();
					
					ModelUtil.deepCopy(newItem,oldItem,Arrays.asList("bed","balcony","curtain","broadband","airCondition","tv","desk","armoire","toilet"));
					oldRoom.setRoomItem(oldItem);
					
					//修改费用配置
					corrFeeRules(newRoom.getFeeRules(),oldRoom);
					resultRooms.add(oldRoom);
				}
				
				//如果有新的房间，则添加新的房间
				int addNum = newRooms.size() - oldRoomsSize;
				if(addNum>0){
					for( int j = i;j<addNum+i ;j++){
						DaRoom newRoom = newRooms.get(j);
						//为什么客户端传过来是空
						DaRoomItem item = newRoom.getRoomItem()==null?new DaRoomItem():newRoom.getRoomItem();
						item.setRoom(newRoom);
						newRoom.setRentState(1);
						newRoom.setSuite(oldModel);
						List<DaFeeRule> roomRules = newRoom.getFeeRules();
						if ( roomRules != null ) {
							for (DaFeeRule daFeeRule : roomRules) {
								daFeeRule.setState(1);
								daFeeRule.setRoom(newRoom);
							}
						}
						resultRooms.add(newRoom);
					}
				}

			}
			oldModel.setRooms(resultRooms);
			oldModel = genericService.update(oldModel);
		}
		daChargeItemService.repaireFixedChargeItem(oldModel);
		
		//合租与整租的修改
		return oldModel;
	}

	
	
	/**
	 * 校正图片修改
	 * @param formAttach
	 * @param oldModel
	 * @return
	 */
	private DaSuite corrImg(List<DaSuiteAttachment> formAttach, DaSuite oldModel) {
		List<DaSuiteAttachment> oldAttachs = oldModel.getAttachments();
		
		if(formAttach==null ||formAttach.size()<=0){
			oldAttachs.removeAll(oldAttachs);
			return oldModel;
		}//清空原来的列表
		
		Map<Integer,DaSuiteAttachment> old = new HashMap<Integer,DaSuiteAttachment>();
		for (DaSuiteAttachment attc : oldAttachs) {
			old.put(attc.getId(),attc);
		}				
		
		Map<Integer,DaSuiteAttachment> newComer = new HashMap<Integer,DaSuiteAttachment>();
		for (DaSuiteAttachment attc : formAttach) {
			newComer.put(attc.getId(),attc);
		}				
		
		//原来的，如里不在现在提交的表单中，，则表示已删除
		for (int i = 0; i < oldAttachs.size(); i++) {
			Integer key = oldAttachs.get(i).getId();
			//原来的在表单中是否存在
			DaSuiteAttachment findObject = newComer.get(key);
			if(findObject == null){
				oldAttachs.remove(old.get(key));
				i--;
			}
		}		
		
		
		Iterator<DaSuiteAttachment> formIter = formAttach.iterator();
		while(formIter.hasNext()){
			DaSuiteAttachment attc = formIter.next();
			if(attc.getId()==null){
				attc.setSuite(oldModel);
				//表示为新增
				oldAttachs.add(attc);
			}
		}
		
		return oldModel;
	}


	/**
	 * 校正FeeRules
	 * @param formRules 表单提供过来的FeeRules
	 * @param oldRules  原有的FeeRules
	 */
	private DaSuite corrFeeRules(List<DaFeeRule> formRules,DaSuite suite) {
		
		List<DaFeeRule> oldRules = suite.getFeeRules();
		
		if(formRules==null ||formRules.size()<=0){
			Iterator<DaFeeRule> feeRules = oldRules.iterator();
			while(feeRules.hasNext()){
				DaFeeRule feeRule = feeRules.next();
				feeRule.setState(0);
			}
			return suite;
		}//改变的是原来的吗?
		
		reviseFeeRule(formRules,oldRules);
		
		//如果现在的feeRule id为空，则表示为新增
		Iterator<DaFeeRule> formIter = formRules.iterator();
		while(formIter.hasNext()){
			DaFeeRule feeRule = formIter.next();
			if(feeRule.getId()==null){
				feeRule.setState(1);
				feeRule.setSuite(suite);
				//表示为新增
				oldRules.add(feeRule);
			}
		}
		//不存在修改的问题
		
		return suite;
		
	}
	
	
	/**
	 * 校正 room FeeRules
	 * @param formRules 表单提供过来的FeeRules
	 * @param oldRules  原有的FeeRules
	 */
	private DaRoom corrFeeRules(List<DaFeeRule> formRules,DaRoom  room) {
		
		List<DaFeeRule> oldRules = room.getFeeRules();
		
		//全部消除
		if(formRules==null ||formRules.size()<=0){
			Iterator<DaFeeRule> feeRules = oldRules.iterator();
			while(feeRules.hasNext()){
				DaFeeRule feeRule = feeRules.next();
				feeRule.setState(0);  //可以真删除
			}
			return room;
		}
		
		reviseFeeRule(formRules, oldRules);
		
		//如果现在的feeRule id为空，则表示为新增
		Iterator<DaFeeRule> formIter = formRules.iterator();
		while(formIter.hasNext()){
			DaFeeRule feeRule = formIter.next();
			if(feeRule.getId()==null){
				feeRule.setState(1);
				feeRule.setRoom(room);
				//表示为新增
				oldRules.add(feeRule);
			}
		}
		//不存在修改的问题
		return room;
		
	}


	private void reviseFeeRule(List<DaFeeRule> formRules,
			List<DaFeeRule> oldRules) {
		//把原有的放到map里面
		Map<Integer,DaFeeRule> old = new HashMap<Integer,DaFeeRule>();
		for (DaFeeRule daFeeRule : oldRules) {
			old.put(daFeeRule.getFeeRuleCfg().getId(),daFeeRule);
		}
		
		//把现在的放到map里面
		Map<Integer,DaFeeRule> newComer = new HashMap<Integer,DaFeeRule>();
		for (DaFeeRule daFeeRule : formRules) {
			FeeRuleCfg cfg = daFeeRule.getFeeRuleCfg();
			newComer.put(cfg.getId(), daFeeRule);
		}
		
		//原来的，如里不在现在提交的表单中，，则表示已删除
		for (int i = 0,len = oldRules.size(); i < len  ; i++) {
			Integer key = oldRules.get(i).getFeeRuleCfg().getId();
			//原来的在表单中是否存在
			DaFeeRule findObject = newComer.get(key);
			if(findObject == null){
				//说明，老的这个在表单中并不存在，也就是说它失效了或是被删除掉了
				oldRules.get(i).setState(0);
			}
			
		}
	}
	
	
	
	
	
	/**
	 * 退房 退租 跳转页面
	 * @param model
	 * @return
	 */
	@Rest(type = "search")
	public Map<String,Object> _unRent(DaRoom model){
		
		//执行自动生成
		//daChargeItemService.autoCreateChargeItem();
		
				
		if ( model.getId() == null ){
			logger.error( "不存在要退租的房间或要退租的房间并未出租" );
			throw new ApplicationException( "不存在要退租的房间或要退租的房间并未出租" );
		}
		
		model = genericService.view( model );
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
		daChargeItemService.triggerCreateCharge(sdf, new Date(), model);
		genericService.refresh(model);
		
		if(model.getRentState()==1){
			logger.error( "已经退租，不能重复退租" );
			return null;
		}
		
		DaAgreement agreement  = model.getAgreement(); 
		
		if( agreement == null){
			logger.error( "该房间不存在有效合约或已自动过期" );
			throw new ApplicationException( "该房间不存在有效合约或已自动过期" );
		}
		
		Map<String,Object> result = new HashMap<String,Object>();
		
		//押金
		BigDecimal deposit = agreement.getDeposit();
		result.put( "deposit",  deposit );
		
		
		
		//得到未收租的收项费 
		List<DaChargeItem> items = model.getChargeItems();
		
		SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd");
		result.put( "lastdate",  sf.format(new Date()));
		
		//得到退租时结算房租的费用 按天数计算 (最后一次未交房租)
		if( items != null && items.size() > 0  ){
			for (int i = 0; i < items.size(); i++) {
				DaChargeItem item  = items.get(i);
				if( item.getChargeType() != null && item.getChargeType()==0 && item.getStatus() == 0){
					Date startDate = item.getDateBeginRecv();
					Date endDate = item.getDateEndRecv();
					Calendar c = Calendar.getInstance();
					c.setTime(new Date());
					c.add(5, 1);
					
					boolean bein = DaChargeItemService.betweenDate(c.getTime(), startDate, endDate);
					if(bein){
						//并不做数据库更新，级联关系只作删除处理，不做更新处理
						item = setPriceWithEndDate(item,new Date());
						result.put( "lastid",  item.getId());
						break;
					}
				}
				
			}
		}
		
		result.put( "items",  items );
		
		BigDecimal itemCount  = new BigDecimal( 0 );
		// 计算出总金额 如果为负数，说明租客还应该补钱。
		for (DaChargeItem daChargeItem : items) {
			itemCount = itemCount.add( daChargeItem.getPriceRecv());
		}
		
		//结算出总金额
		BigDecimal resultCount = deposit.subtract(itemCount);
		result.put( "resultCount",  resultCount );
		
		return result;
	}
	
	
	/**
	 * 计算item的开始日期至unRentDate止，的费用。
	 * @param item
	 * @param unRentDate
	 * @return
	 */
	@Rest(type = "search")
	public DaChargeItem setPriceWithEndDate(DaChargeItem model,Date unRentDate){
		BigDecimal price = getPriceWithEndDate(model,unRentDate);
		//经过计算后才能设置下面的两个参数，否则会导致计算错误
		model.setDateEndRecv(unRentDate);
		model.setPriceRecv(price);
		return model;
	}
	
	
	/**
	 * 获取价格
	 * @param model
	 * @param unRentDate
	 * @return
	 */
	@Rest(type = "search")
	public BigDecimal getPriceWithEndDate(DaChargeItem model,Date unRentDate){
		
		 model =  genericService.load(model);
		 if(model == null ){
			 return new BigDecimal(0);
		 }
		 genericService.detach(model);
		
		Date startDate = model.getDateBeginRecv();
		Date endDate = model.getDateEndRecv();
		
		if(endDate.compareTo(unRentDate)==0){
			return model.getPriceRecv();
		}
		
		try {
				//一个周期内的总天数
				Integer totalDayCount = DaChargeItemService.daysBetween(startDate, endDate);
				//一个周期应收取的房租
				BigDecimal totalRentPay = model.getRoom().getAgreement().getRentPay().multiply(new BigDecimal(model.getRoom().getAgreement().getPayNum()));
				
				//每一天多少钱
				BigDecimal dayFee = totalRentPay.divide(new BigDecimal(totalDayCount),2,BigDecimal.ROUND_UP);
				
				//到目前为止的天数
				Integer dayCount = DaChargeItemService.daysBetween(startDate, unRentDate)+1;
				//目前为止天数应收取的费用
				BigDecimal  totalDayFee = dayFee.multiply(new BigDecimal(dayCount)).setScale(0,BigDecimal.ROUND_HALF_UP);
				return totalDayFee;
		}catch(Exception e){
			logger.error("日期计算出错");
			throw new ApplicationException("日期计算出错");
		}
	}
	
	
	/**
	 * 退租
	 * @param model
	 * @param totalRecv
	 * @param totalFee
	 * @param formitems
	 * @return
	 */
	
	@Rest(type = "unRent")
	public Result unRent(DaAgreement model ,BigDecimal totalRecv, BigDecimal totalFee,List<DaChargeItem> formitems ,String remark){
		//改变合约的状态--删除合约
		model = genericService.load( model );
		model.setAgreementState(1);
		genericService.merge(model);
		
		//改变房间的状态
		DaRoom room = model.getRoom();
		DaSuite suite = room.getSuite();
		
		if(room.getRentState().equals(0)){
			
			room.setRentState(1);
			room.setAgreement(null);
			genericService.merge( room );
			
			if(suite.getRentType() == 0){
				suite.setRentState(1);
				genericService.merge( suite );
			}else{
				//根据实际情况来判断它，如果它是一个状态为2的情况，那么还要得新设置一下它 合租情况，退租要对房源进行下理
				synSuiterentStatus(suite.getId());
			}
			
			//改变收费项的状态 生成一笔费用
			DaChargeBill bill = new DaChargeBill();
			bill.setDateActual(new Date());
			bill.setRoom(room);
			bill.setAmountActual( new BigDecimal(0).subtract(totalFee) );
			bill.setAmountRecv( new BigDecimal(0).subtract(totalRecv) );
			bill.setBalance(bill.getAmountActual().subtract(bill.getAmountRecv()));
			bill.setRemark(remark);
			List<DaChargeItem> billItems = new ArrayList<DaChargeItem>();
			
			
			Map<Integer,DaChargeItem> itemMap = new HashMap<Integer, DaChargeItem>();
			for (DaChargeItem daChargeItem : formitems) {
				itemMap.put(daChargeItem.getId(), daChargeItem);
			}
			
			//获取原本未收取的费用
			List<DaChargeItem> items = room.getChargeItems();
			
			//根据实际情况，修正费用项
			for (DaChargeItem daChargeItem : items) {
				//设置为已收费用
				daChargeItem.setStatus( 1 );
				daChargeItem.setChargeBill( bill );
				DaChargeItem formItem = itemMap.get(daChargeItem.getId());
				
				//应收实收与时间做相应调整 *****
				daChargeItem.setDateEndRecv(formItem.getDateEndRecv());
				daChargeItem.setPriceRecv(formItem.getPriceRecv());
				daChargeItem.setPriceActual(formItem.getPriceActual());
				
				billItems.add( daChargeItem );
			}
			
			bill.setChargeItems( billItems );
			
			//添加bill的同时 修改chargeItems
			genericService.add( bill );
			//记录财务流水
			daFinanceStatementService.addInternal(room, bill.getAmountActual().multiply(BigDecimal.valueOf(-1)), 3, new Date(), 0, "退租:"+bill.getRemark());
			
			//发布房源
			roomRetrievalService.publishDaRoom(room, false);
		}
		
		Result result = new ServletRedirectResult("/da/landlord/daSuite.manager.html?model.id="+suite.getId());
		objectFactory.autoWireBean(result);
		return result;
	}
	
	
	/**
	 * 获取daSuite的最早合约开始时间
	 * @param daSuite
	 * @return
	 */
	@Rest(type = "search")
	public Date getEarliestAgreementDate(DaSuite daSuite){
		
		List<DaRoom> rentRooms = daSuite.getRentRooms();
		Date earliestDate = Calendar.getInstance().getTime();
		
		if (rentRooms != null && rentRooms.size() > 0) {
			for (DaRoom daRoom : rentRooms) {
				DaAgreement agreement = daRoom.getAgreement();
				if (earliestDate.compareTo(agreement.getRentBeginDate()) > 0) {
					earliestDate = agreement.getRentBeginDate();
				}
			}
		}
		
		return earliestDate;
	}
	

	/**
	 * 通过AJAX，动态添加收费项，并且返回添加好的收费项的ids
	 * @param model
	 * @return
	 */
	@Rest(type = "search")
	public List<FeeRuleCfg> easyRuleCfg( List<FeeRuleCfg> model ){
		
		List< FeeRuleCfg > result = new ArrayList< FeeRuleCfg >();
		
		for (FeeRuleCfg feeRuleCfg : model) {
			feeRuleCfg.getFeeRuleCfgDesc().setCalcMode( FeeRuleCalcMode.normal );
			feeRuleCfg.getFeeRuleCfgCalc().setRentCycle( 1 );
			if(feeRuleCfg.getFeeRuleCfgDesc().getType() == FeeRuleType.fixed){
				feeRuleCfg.getFeeRuleCfgDesc().setUnit("");
			}
			
			feeRuleCfg = feeRuleCfgService.addFeeRuleCfg( feeRuleCfg );
			feeRuleCfg = genericService.load( feeRuleCfg );
			result.add( feeRuleCfg );
		}
		
		return result;
	}
	
	@Rest(type = "search")
	public PageInfo<DaRoom> searchRoom(DaSuite model, String tenantUserName, Integer chargeState, Integer expiredLeave) {
		
		LandlordUser landlordUser = landlordUserService.getLoginUser();
		StringBuilder sb = new StringBuilder();
		QLInfo ql = new QLInfo();
		sb.append("select a from " + DaSuite.class.getName() + " b left join b.rooms a");
		boolean isAppend = false;
		if (landlordUser instanceof LandlordAssistUser)
		{
			sb.append(" left join b.landlordUsers c where  c.id = ?");
			ql.addParam(landlordUser.getId());
			isAppend = true;
		}
		if (isAppend)
		{
			sb.append(" and b.rentState is not null ");
		}
		else
		{
			sb.append(" where b.rentState is not null ");
		}
		
		
		if (StringUtils.isNotEmpty(model.getName())) {
			sb.append(" and a.suite.name like ? ");
			ql.addParam("%" + model.getName().trim() + "%");
		}
		
		
		
		if (StringUtils.isNotEmpty(tenantUserName)) {
			sb.append(" and a.agreement is not null and a.agreement.tenantUser.name like ?");
			ql.addParam("%" + tenantUserName + "%");
		}
		if (model.getRentType() != null) {
			sb.append(" and b.rentType = ?");
			ql.addParam(model.getRentType());
		}
		if (model.getRentState() != null) {
			if (DaSuite.RENTSTATE_FREE.equals(model.getRentState())){
				sb.append(" and a.agreement is null");
			} else if (DaSuite.RENTSTATE_RENTED.equals(model.getRentState())) {
				sb.append(" and a.agreement is not null");
			}
		}
		if (chargeState != null) {
			if (chargeState == 0) { //已缴费
				sb.append(" and a.agreement is not null and exists (from "+ DaChargeBill.class.getName() +" c inner join c.chargeItems d with d.chargeType = ? where c.agreement= a.agreement and date_add_interval(d.dateEndRecv,-a.agreement.advanceNum) >= ? )");
				ql.addParam(DaChargeItem.CHARGE_TYPE_RENTAL);
				ql.addParam(DateTimeUtil.throwTimeForDate(new Date()));
			} else if (chargeState == 1) { //未缴费
				//sb.append(" and a.chargeItems.size != 0");
				sb.append(" and a.agreement is not null and not exists (from "+ DaChargeBill.class.getName() +" c inner join c.chargeItems d with d.chargeType = ? where c.agreement= a.agreement and date_add_interval(d.dateEndRecv,-a.agreement.advanceNum) >= ? )");
				ql.addParam(DaChargeItem.CHARGE_TYPE_RENTAL);
				ql.addParam(DateTimeUtil.throwTimeForDate(new Date()));
			}
		}
		if (expiredLeave != null) {
			Calendar now = Calendar.getInstance();
			if (expiredLeave !=null) {
				now.add(Calendar.DATE, expiredLeave);
			}
			sb.append(" and a.agreement is not null and a.agreement.rentEndDate <= ?");
			ql.addParam(now.getTime());
		}
		//sb.append(" order by b.id desc, a.id asc");
		ql.setQl(sb.toString());
		ql.setDisablePermissionFilter(false);
		ql.setCompiledSort("b.name, a.id");
		ql.setDir("asc,asc");
		
		//计算每个suite下符合条件的room数量
		@SuppressWarnings("unchecked")
		PageInfo<DaRoom> pageInfo = genericService.searchByQl(ql);
		int prevSuiteId = 0;
		int roomCount = 0;
		int i = 0;
		for (i = 0; i<pageInfo.getData().size(); i++) {
			DaRoom room = pageInfo.getData().get(i);
			if (prevSuiteId != room.getSuite().getId()) {
				if (roomCount != 0) {
					pageInfo.getData().get(i-1).getSuite().setRoomSize(roomCount);
				}
				roomCount = 1;
				prevSuiteId = room.getSuite().getId();
			} else {
				roomCount ++;
			}
			
			setRoomHasPaid(room);
		}
		if (roomCount != 0) {
			pageInfo.getData().get(i-1).getSuite().setRoomSize(roomCount);
		}
		
		return pageInfo;
	}
	
	public void setRoomHasPaid (DaRoom dbRoom) {
		if (Room.RENT_STATE_ALREADY.equals(dbRoom.getRentState()) && dbRoom.getAgreement() != null && dbRoom.getAgreement().getChargeBills() != null && dbRoom.getAgreement().getChargeBills().size() > 0 && dbRoom.getAgreement().getChargeBills().get(0).getChargeItems() != null && dbRoom.getChargeBills().get(0).getChargeItems().size() > 0 && DateTimeUtil.GetDateWithAdvanceNum(dbRoom.getChargeBills().get(0).getChargeItems().get(0).getDateEndRecv(), dbRoom.getAgreement().getAdvanceNum()).compareTo(DateTimeUtil.throwTimeForDate(new Date())) >= 0) {
			dbRoom.setHasPaid(true);
		} else {
			dbRoom.setHasPaid(false);
		}
	}
	
	@Rest(type="search")
	public List<DaSuite> searchDaSuite() {
		DaSuite model = new DaSuite();
		LandlordUser landlordUser = landlordUserService.getLandlordUser();
		model.setLandlordUser(landlordUser.getOwnerUser());
		return genericService.searchByModel(model, Condition.DEFAULT).getData();
	}
}
